home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i068: Tool to aide in merging password files
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Don Libes <libes@cme-durer.arpa>
- Posting-number: Volume 18, Issue 68
- Archive-name: pwdiff
-
- pwdiff takes multiple password files and compares them in an
- intelligent way. For instance, it will report on different names
- with the same uid, but let pass the same name with the same uid.
-
- What happened was that we started out with one shared password file in
- a small LAN environment. Over time, more machines came on-line.
- New administrators sometimes shared the old password file, and
- sometimes just copied it. Gradually it diverged, so that some of the
- uids mapped to multiple users across the LAN.
-
- Eventually our LAN got big enough, so that we hired a sitewide admin,
- and he wanted to use one common password file. This makes NFS access
- much easier, for example. So I wrote this program to solve his
- problem. I figure this very same thing must happen to lots of sites,
- so to save you some grief, here it is.
- Don Libes
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: Makefile README pwdiff.8 pwdiff.c
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo Extracting Makefile \(entered by hand, no error checking\)
- sed "s/^X//" >Makefile <<'END_OF_FILE'
- Xall: pwdiff pwdiff.8
- X
- Xinstall: all
- X @echo Installing according to local convention
- X
- Xpwdiff: pwdiff.c
- X $(CC) -o pwdiff $(CFLAGS) pwdiff.c
- END_OF_FILE
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(1089 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- Xpwdiff takes multiple password files and compares them in an
- Xintelligent way. For instance, it will report on different names
- Xwith the same uid, but let pass the same name with the same uid.
- X
- XI wrote it one day when we had to join two password files from
- Xdifferent machines.
- X
- XWhat happened was that we started out with one shared password file in
- Xa small LAN environment. Over time, more machines came on-line.
- XNew administrators sometimes shared the old password file, and
- Xsometimes just copied it. Gradually it diverged, so that some of the
- Xuids mapped to multiple users across the LAN.
- X
- XEventually our LAN got big enough, so that we hired a sitewide admin,
- Xand he wanted to use one common password file. This makes NFS access
- Xmuch easier, for example. So I wrote this program to solve his
- Xproblem. I figure this very same thing must happen to lots of sites,
- Xso to save you some grief, here it is. Send bugs, improvements, and
- Xcash to me.
- X
- XDon Libes
- XNational Bureau of Standards
- XBldg 220, Rm A-127
- XGaithersburg, MD 20899
- X(301) 975-3535
- Xlibes@cme-durer.arpa
- Xuunet!cme-durer!libes
- END_OF_FILE
- if test 1089 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'pwdiff.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pwdiff.8'\"
- else
- echo shar: Extracting \"'pwdiff.8'\" \(724 characters\)
- sed "s/^X//" >'pwdiff.8' <<'END_OF_FILE'
- X.TH PWDIFF 8 "25 June 1988"
- X.SH NAME
- Xpwdiff \- find differences in password files
- X.SH SYNOPSIS
- Xpwdiff file1 file2 file3 ...
- X.SH DESCRIPTION
- XThis program compares multiple password files and reports on uid or
- Xname conflicts that would prevent the files from being merged.
- X.PP
- XFor example, if uid 27 is don in file1 and susan in file2, this will be
- Xdetected.
- X.PP
- XThe program also notes syntactically incorrect lines and nicknames
- X(the user name does not match the home directory). Since many low
- Xuids are nicknames (root, uucp, etc.) a compile-time constant controls
- Xa cut-off below which nicknames are ignored. As distributed, uids
- Xbelow 20 are not checked for nicknames.
- X.SH AUTHOR
- XDon Libes, National Bureau of Standards
- END_OF_FILE
- if test 724 -ne `wc -c <'pwdiff.8'`; then
- echo shar: \"'pwdiff.8'\" unpacked with wrong size!
- fi
- # end of 'pwdiff.8'
- fi
- if test -f 'pwdiff.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pwdiff.c'\"
- else
- echo shar: Extracting \"'pwdiff.c'\" \(3311 characters\)
- sed "s/^X//" >'pwdiff.c' <<'END_OF_FILE'
- X/* Check multiple passwd files for uid/name overlap - Don Libes */
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X
- X#define TRUE 1
- X#define FALSE 0
- X
- Xstruct tinypasswd { /* like struct pwd but missing some entries */
- X char *name;
- X char *dir;
- X struct tinypasswd *next; /* other entries mapping to same uid */
- X char *file; /* file this entry was found in */
- X};
- X
- X#define MINUSERUID 20 /* don't check uids below this for */
- X /* names to match directories */
- X#define MAXLINELEN 132
- X#define MAXUID 5700 /* largest uid we might possibly see */
- X#define NOBODY -2
- X#define skipuid(x) (x == NOBODY) /* any uids to skip. If none */
- X /* then just define to be 0 */
- X
- Xstruct tinypasswd *pwds[MAXUID];
- Xchar line[MAXLINELEN];
- Xstruct tinypasswd *pwd;
- X
- Xchar *malloc();
- Xchar *newstr();
- Xchar *rindex();
- Xstruct passwd *fgetpwent();
- X#define new(type) (type *)malloc(sizeof(type))
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar **argv;
- X{
- X int file;
- X int uid;
- X FILE *pfp;
- X struct passwd *staticpwd;
- X char *leaf;
- X
- X for (uid=0;uid<MAXUID;uid++) pwds[uid] = NULL;
- X
- X for (file=1;file<argc;file++) {
- X if (NULL == (pfp = fopen(argv[file],"r"))) {
- X perror(argv[file]);
- X continue;
- X }
- X
- X while (NULL != (staticpwd = fgetpwent(pfp))) {
- X if (pwd == NULL) {
- X if (NULL == (pwd = new(struct tinypasswd))) {
- X printf("malloc: out of space\n");
- X exit(-1);
- X }
- X }
- X
- X /* skip Sun yp hook */
- X if (staticpwd->pw_name[0] == '+') continue;
- X
- X pwd->name = newstr(staticpwd->pw_name);
- X pwd->dir = newstr(staticpwd->pw_dir);
- X uid = staticpwd->pw_uid;
- X
- X if (skipuid(uid)) continue;
- X if (uid < 0 || uid >= MAXUID) {
- X printf("%s: uid %d out of range\n",
- X argv[file],uid);
- X continue;
- X }
- X
- X /* check for matching directories on large uids */
- X if (uid > MINUSERUID) {
- X if (0 == (leaf = rindex(pwd->dir,'/'))) {
- X printf("%s: no leaf in directory %s\n",
- X argv[file],line);
- X } else if (0 != strcmp(pwd->name,1+leaf)) {
- X printf("%s: nickname %s has directory %s\n",
- X argv[file],pwd->name,pwd->dir);
- X }
- X }
- X
- X pwd->file = argv[file];
- X pwd->next = NULL;
- X
- X if (!hash_pwd(&pwds[uid],pwd)) {
- X free(pwd->name);
- X free(pwd->dir);
- X } else pwd = NULL;
- X }
- X fclose(pfp);
- X }
- X
- X /* scan down list looking for dups */
- X for (uid=0;uid<MAXUID;uid++) {
- X /* no pwd with this uid */
- X if (pwds[uid] == NULL) continue;
- X
- X /* no other pwd with this uid */
- X if (pwds[uid]->next == NULL) continue;
- X
- X print_pwd(uid);
- X }
- X}
- X
- Xprint_pwd(uid)
- Xint uid;
- X{
- X struct tinypasswd *p;
- X
- X for (p = pwds[uid];p;p=p->next) {
- X printf("%6d %20s %40s\n",uid,p->name,p->file);
- X }
- X}
- X
- X/* returns TRUE if pwd stored, FALSE if not stored */
- Xhash_pwd(pep,p)
- Xstruct tinypasswd **pep; /* pwds entry pointer */
- Xstruct tinypasswd *p;
- X{
- X int different = FALSE;
- X struct tinypasswd *pptr; /* pointer to open-hashed pwd entries */
- X struct tinypasswd *lastp; /* where to append new struct passwd */
- X
- X if (NULL == *pep) {
- X *pep = p;
- X return(TRUE);
- X }
- X
- X for (pptr = *pep;pptr;pptr=pptr->next) {
- X lastp = pptr;
- X if (different) continue; /* just get to end of list */
- X if (0 != strcmp(pptr->name,p->name)) different = TRUE;
- X }
- X if (different) lastp->next = p;
- X
- X return(different);
- X}
- X
- Xchar *newstr(s)
- Xchar *s;
- X{
- X char *news;
- X
- X if (!(news = malloc(1+strlen(s)))) {
- X printf("newstr: out of space\n");
- X exit(0);
- X }
- X strcpy(news,s);
- X return(news);
- X}
- END_OF_FILE
- if test 3311 -ne `wc -c <'pwdiff.c'`; then
- echo shar: \"'pwdiff.c'\" unpacked with wrong size!
- fi
- # end of 'pwdiff.c'
- fi
- echo shar: End of shell archive.
- exit 0
-
-